<?php
namespace Core\Forms;

use Phalcon\Forms\Element as PhalconElement;
use Phalcon\Forms\Exception;
use Phalcon\Tag;
use Phalcon\Di;

/**
 * Class Element
 * @package Core\Forms
 */
class Element extends PhalconElement
{
    /**
     * @var
     */
    protected $_default;
    /**
     * @var \Phalcon\DiInterface
     */
    protected $_dependencyInjector;
    /**
     * @var object
     */
    protected $_eventsManager;

    /**
     * Element constructor.
     * @param $name
     * @param null $attributes
     */
    public function __construct(string $name, $attributes = null)
    {
        parent::__construct($name, $attributes);
        $this->_dependencyInjector = Di::getDefault();
        $this->_eventsManager = $this->_dependencyInjector->getShared('eventsManager');
    }

    /**
     * @return mixed
     */
    public function getDI()
    {
        return $this->_dependencyInjector;
    }

    /**
     * @param $value
     * @return $this
     */
    public function setDefault($value)
    {
        if (is_object($value)) {
            $value = (array)$value;
        }
        $this->_default = $value;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getDefault()
    {
        $this->_eventsManager->fire('formElement:getDefault', $this, $this->_default);
        return $this->_default;
    }

    /**
     * @return mixed
     */
    public function getValue()
    {
        $this->_value = parent::getValue();
        $this->_eventsManager->fire('formElement:getValue', $this, $this->_value);
        return $this->_value;
    }


    /**
     * @param $value
     * @return $this
     */
    public function setValue($value)
    {
        $this->_value = $value;
        return $this;
    }

    /**
     * Returns an array of prepared attributes for \Phalcon\Tag helpers
     * according to the element's parameters
     *
     * @param array|null $attributes
     * @param boolean|null $useChecked
     * @return array
     * @throws Exception
     */
    public function prepareAttributes(array $attributes = null, $useChecked = null)
    {
        /* Type check */
        if (is_array($attributes) === false) {
            $attributes = array();
        }

        if (is_null($useChecked) === true) {
            $useChecked = false;
        } elseif (is_bool($useChecked) === false) {
            throw new Exception('Invalid parameter type.');
        }

        //Create an array of parameters
        $attributes[0] = $this->_name;

        //Merge passed parameters with default ones
        if (is_array($this->_attributes) === true) {
            //@note we are potentially overriding data from $attributes
            $attributes = array_merge($this->_attributes, $attributes);
        }

        //Get the current element's value
        $value = $this->getDefault();

        //If the widget has a value set it as default value
        if (is_null($value) === false) {
            if ($useChecked === true) {
                /*
                                     * Check if the element already has a default value, compare it with the one in the
                                     * attributes, if they are the same mark the element as checked
                */
                if (isset($attributes['value']) === true) {
                    if ($attributes['value'] === $value) {
                        $attributes['checked'] = 'checked';
                    }
                } else {
                    //Evaluate the current value and mark the check as checked
                    if ($value == true) {
                        $attributes['checked'] = 'checked';
                    }

                    $attributes['value'] = $value;
                }
            } else {
                $attributes['value'] = $value;
            }
        }

        return $attributes;
    }

    /**
     * Renders the element widget
     *
     * @param array|null $attributes
     * @return string
     * @throws Exception
     */
    public function render($attributes = null)
    {
        if (is_array($attributes) === false &&
            is_null($attributes) === false
        ) {
            throw new Exception('Invalid parameter type.');
        }

        return Tag::textField($this->prepareAttributes($attributes));
    }
}